package org.lc.stk.service.baseInfo.impl;

import java.util.List;

import org.lc.stk.dao.baseInfo.CengciRepository;
import org.lc.stk.model.baseInfo.Cengci;
import org.lc.stk.service.baseInfo.CengciService;
import org.lc.stk.service.exception.BusinessException;
import org.lc.stk.service.support.QuerySpecifications;
import org.lc.stk.web.dto.cengci.CengciQuery;
import org.lc.stk.web.dto.cengci.CreateCengciRequest;
import org.lc.stk.web.dto.cengci.UpdateCengciRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@Transactional(readOnly = true)
public class CengciServiceImpl implements CengciService {

    private static final Logger logger = LoggerFactory.getLogger(CengciServiceImpl.class);

    @Autowired
    private CengciRepository cengciRepository;

    @Override
    @Transactional
    public Cengci create(CreateCengciRequest request) {
        // 检查编码唯一性
        if (isCodeExists(request.getCode(), null)) {
            throw new BusinessException("培养层次编码已存在: " + request.getCode());
        }
        
        // 检查名称唯一性
        if (isNameExists(request.getName(), null)) {
            throw new BusinessException("培养层次名称已存在: " + request.getName());
        }

        Cengci cengci = new Cengci();
        cengci.setCode(request.getCode());
        cengci.setName(request.getName());
        cengci.setOrderNum(request.getOrderNum());
        cengci.setRemark(request.getRemark());
        cengci.setIsDeleted(false);

        logger.info("Creating new Cengci: {}", request.getCode());
        return cengciRepository.save(cengci);
    }

    @Override
    @Transactional
    public Cengci update(UpdateCengciRequest request) {
        Cengci existing = getById(request.getId());
        
        // 检查编码唯一性
        if (StringUtils.hasText(request.getCode()) 
            && !request.getCode().equals(existing.getCode()) 
            && isCodeExists(request.getCode(), request.getId())) {
            throw new BusinessException("培养层次编码已存在: " + request.getCode());
        }
        
        // 检查名称唯一性
        if (StringUtils.hasText(request.getName()) 
            && !request.getName().equals(existing.getName()) 
            && isNameExists(request.getName(), request.getId())) {
            throw new BusinessException("培养层次名称已存在: " + request.getName());
        }

        if (StringUtils.hasText(request.getCode())) {
            existing.setCode(request.getCode());
        }
        if (StringUtils.hasText(request.getName())) {
            existing.setName(request.getName());
        }
        if (request.getOrderNum() != null) {
            existing.setOrderNum(request.getOrderNum());
        }
        if (request.getRemark() != null) {
            existing.setRemark(request.getRemark());
        }
        if (request.getIsDeleted() != null) {
            existing.setIsDeleted(request.getIsDeleted());
        }

        logger.info("Updating Cengci: {}", existing.getCode());
        return cengciRepository.save(existing);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        Cengci cengci = getById(id);
        cengci.setIsDeleted(true);
        logger.info("Soft deleting Cengci: {}", cengci.getCode());
        cengciRepository.save(cengci);
    }

    @Override
    public Cengci getById(Integer id) {
        return cengciRepository.findById(id)
                .orElseThrow(() -> new BusinessException("培养层次不存在: " + id));
    }

    @Override
    public Cengci getByCode(String code) {
        return cengciRepository.findByCodeAndIsDeletedFalse(code)
                .orElseThrow(() -> new BusinessException("培养层次不存在: " + code));
    }

    @Override
    public Page<Cengci> query(CengciQuery query, Pageable pageable) {
        Specification<Cengci> spec = buildSpecification(query);
        return cengciRepository.findAll(spec, pageable);
    }

    @Override
    public List<Cengci> listAll() {
        return cengciRepository.findByIsDeletedFalseOrderByOrderNumAsc();
    }

    @Override
    public boolean isCodeExists(String code, Integer excludeId) {
        if (excludeId == null) {
            return cengciRepository.findByCodeAndIsDeletedFalse(code).isPresent();
        }
        return cengciRepository.existsByCodeAndIdNot(code, excludeId);
    }

    @Override
    public boolean isNameExists(String name, Integer excludeId) {
        if (excludeId == null) {
            return cengciRepository.findByNameAndIsDeletedFalse(name).isPresent();
        }
        return cengciRepository.existsByNameAndIdNot(name, excludeId);
    }

    private Specification<Cengci> buildSpecification(CengciQuery query) {
        return QuerySpecifications.and(
                QuerySpecifications.like("code", query.getCode()),
                QuerySpecifications.like("name", query.getName()),
                query.getIncludeDeleted() ? null : QuerySpecifications.equal("isDeleted", false)
        );
    }
}